package de.hauschild.gmltracer.tracer.impl;

import org.apache.commons.math.geometry.Vector3D;

import de.hauschild.gmltracer.tracer.Ray;

public class Vector3DUtils {

  public static boolean equals(final Vector3D a, final Vector3D b) {
    return equals(a, b, 0.0);
  }

  public static boolean equals(final Vector3D a, final Vector3D b, final double eps) {
    return Math.abs(a.getX() - b.getX()) <= eps && Math.abs(a.getY() - b.getY()) <= eps
        && Math.abs(a.getZ() - b.getZ()) <= eps;
  }

  public static Vector3D multiplyComponentwise(final Vector3D a, final Vector3D b) {
    return new Vector3D(a.getX() * b.getX(), a.getY() * b.getY(), a.getZ() * b.getZ());
  }

  public static Ray reflectRay(final Ray ray, final Vector3D normal) {
    // vector of incoming ray
    final Vector3D vector = new Vector3D(ray.getEnd().getX() - ray.getStart().getX(), ray.getEnd().getY()
        - ray.getStart().getY(), ray.getEnd().getZ() - ray.getStart().getZ());
    // dot product of incoming ray vector and surface normal
    final double dotProduct = Vector3D.dotProduct(vector, normal);
    // reflected vector
    final Vector3D reflectedVector = new Vector3D(-vector.getX() + 2 * normal.getX() * dotProduct, -vector.getY() + 2
        * normal.getY() * dotProduct, -vector.getZ() + 2 * normal.getZ() * dotProduct);
    // reflected ray
    return new Ray(ray.getEnd(), ray.getEnd().add(reflectedVector));
  }

}
